/****************************************************************************
*Copyright(C),2018-?,西南石油大学XL结对项目小组
*文件名: argparser.c
*内容简述：通过一系列的函数来对arguments解析
*文件历史：无
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define COMMAND 100
#define PARAMETER 200
#define _EOF 300
#define INT 10
#define CHAR 20
#define STRING 30
#define MAX_LENGTH 100
#define TRUE 1
#define FALSE 0
#define MAX_PARAMETER_NUMBER 10
#define MAX_COMMAND_NUMBER 30

char *all_commands[MAX_COMMAND_NUMBER] = { NULL };
int number_of_command = 0;

typedef struct {
	int type;
	char *value;
}Token;

typedef struct {
	char *text;
	char current_char;
	int pos;
}Lexer;

// multiple parameter using struct to pass...
typedef struct {
	int number_of_parameter;
	char *param;
}Parameter;

typedef struct node {
	char *command;
	char *help;
	int required;
	int require_parameter;
	int triggered;
	struct node *next;
	char *parameter;
}Command;

typedef struct {
	Lexer *lexer;
	Token current_token;
	Command *head;
}ParameterInterpreter;


/*
	Usage Example:
	// 创建lexer 将当前的lexer与argc，argv传入
	Lexer l = initLexer(l, argc, argv);
	// 初始化Comand链表的头节点
	Command *head = initCommand();
	// 自定义Command	
	putCommand(head, strdup("-m"),  strdup("-m's help"), FALSE, TRUE);
	putCommand(head, strdup("-d"),  strdup("-m's help"), TRUE, FALSE);
	putCommand(head, strdup("-s"),  strdup("-m's help"), FALSE, TRUE);
	// 初始化parameterInterpreter，将初始化过的Lexer和Command链表的头节点传入
	ParameterInterpreter pi = initParameterInterpreter(&l, head);
	// 调用handleParamter(&pi) 返回所有处理结果 
	Command *result = handleParameter(&pi);
	// 调用getTriggeredComandList 将命令行中出现了的参数返回
	Command *a = getTriggeredComandList(result);
	// 测试用。。。
	replCommandList(a);
	
*/


/****************************************************************************
*函数名:char *typeToStrin1g(Token t)
*功能:将Token中用int表示的type1转换成对应type字符串
*输入:t:Tok1en
*输出:指向t的type转化成中文后的1字符串指针
*/
char *typeToString(Token t);


/****************************************************************************
*函数名:void replToken(Token t)
*功能:将Token输出在屏幕上 相当于重写了java中的toString方法
*输入:t:Token
*输出:无
*/
void replToken(Token t);


/****************************************************************************
*函数名:Lexer initLexer(Lexer l, int argc, char *argv[])
*功能:初始化词法分析器
*输入:t:l:Lexer argc:main函数中的argc argv:main函数中的argv
*输出:初始化过的Lexer
*/
Lexer initLexer(Lexer l, int argc, char *argv[]);

/****************************************************************************
*函数名:void advance(Lexer *l)
*功能:使词法分析器指向读入text中的下一位
*输入:l:Lexer
*输出:无
*/
void advance(Lexer *l);

/****************************************************************************
*函数名:void skipWhitespace(Lexer *l)
*功能:使解析时跳过空格
*输入:l:Lexer
*输出:无
*/
void skipWhitespace(Lexer *l);

/****************************************************************************
*函数名:int isValidChar(char ch)
*功能:判断当前解析的char是否合法
*输入:ch:char
*输出:1代表合法 0代表不合法
*/
int isValidChar(char ch);

/****************************************************************************
*函数名:void checkWhitespace(Lexer *l)
*功能:判断命令与参数是否通过空格隔开
*输入:l:Lexer
*输出:无
*/
void checkWhitespace(Lexer *l);

/****************************************************************************
*函数名:char* command(Lexer *l)
*功能:词法分析器返回一个解析成功的command
*输入:l:Lexer
*输出:解析成功命令的字符串
*/
char* command(Lexer *l);

/****************************************************************************
*函数名:char* parameter(Lexer *l)
*功能:词法分析器返回一个解析成功的parameter
*输入:l:Lexer
*输出:解析成功参数的字符串
*/
char* parameter(Lexer *l);

/****************************************************************************
*函数名:Token getNextToken(Lexer *l)
*功能:返回解析成功的Token
*输入:l:Lexer
*输出:当前解析成功的Token
*/
Token getNextToken(Lexer *l);

/****************************************************************************
*函数名:Command *initCommand()
*功能:初始化参数链表
*输入:无
*输出:Comand*
*/
Command *initCommand();

/****************************************************************************
*函数名:Command *getTailCommand(Command *head)
*功能:获取Command链表中put上去的最后一个命令
*输入:head:链表的头
*输出:链表的尾节点
*/
Command *getTailCommand(Command *head);

/****************************************************************************
*函数名:void putCommand(Command *head, char *command, char *help, int required, int require_parameter)
*功能:自定义解析的命令 并添加到命令链表中
*输入:head:命令链表的头节点 command:命令的字符串表示 help:帮助信息 required:是否为必须命令 required_parameter:命令是否携带参数
*输出:无
*/
void putCommand(Command *head, char *command, char *help, int required, int require_parameter);

/****************************************************************************
*函数名:ParameterInterpreter initParameterInterpreter(Lexer *l, Command *head)
*功能:初始化参数解释器
*输入:l:Lexer head:命令链表头节点
*输出:初始成功的阐述解释器
*/
ParameterInterpreter initParameterInterpreter(Lexer *l, Command *head);

/****************************************************************************
*函数名:void eat(ParameterInterpreter *pi, int type)
*功能:判断当前规则下所需的参数类型是否符合传入的参数类型 如果否 则退出
*输入:pi:ParameterInterpreter type:预期中的参数类型
*输出:无
*/
void eat(ParameterInterpreter *pi, int type);

/****************************************************************************
*函数名:int isCommandExist(char *value)
*功能:判断参数是否存在 防止用户传入一个无法识别的参数
*输入:value:Command字符串
*输出:1代表存在 0代表不存在
*/
int isCommandExist(char *value);

/****************************************************************************
*函数名:void switchTriggerState(Command *head, Token t)
*功能:将出现在命令行中的参数设置为激活状态 方便调用对应功能代码
*输入:head:命令链表 t:当前的Token
*输出:无
*/
void switchTriggerState(Command *head, Token t);

/****************************************************************************
*函数名:Token base(ParameterInterpreter *pi)
*功能:解析 -x 的规则
*输入:pi:当前的参数解析器
*输出:解析成功的命令
*/
Token base(ParameterInterpreter *pi);

/****************************************************************************
*函数名:Command *findCommandByName(Command *head, char *command)
*功能:通过command的名称判断命令是否存在
*输入:head:命令链表的头节点 command:待查找命令的名称
*输出:Command指针或NULL
*/
Command *findCommandByName(Command *head, char *command);

/****************************************************************************
*函数名:void combination(ParameterInterpreter *pi)
*功能:处理 (-x parameter?)+ 规则
*输入:pi:参数解释器
*输出:无
*/
void combination(ParameterInterpreter *pi);

/****************************************************************************
*函数名:Command *handleParameter(ParameterInterpreter *pi)
*功能:调用Combination方法来处理参数
*输入:pi:参数解释器
*输出:解析完成的命令链表的头节点
*/
Command *handleParameter(ParameterInterpreter *pi);

/****************************************************************************
*函数名:Command *getTriggeredComandList(Command *head)
*功能:将激活状态的命令从命令列表中截取出来
*输入:head:命令链表的头节点
*输出:截取完过后的命令链表
*/
Command *getTriggeredComandList(Command *head);

/****************************************************************************
*函数名:void replCommandList(Command *head)
*功能:将命令链表表示出来 相当于重写了java中的toString方法
*输入:命令链表的头结点
*输出:
*/
void replCommandList(Command *head);